﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Tools.Core
{
    public class TasksQueueHelper
    {
        private static Dictionary<string, TasksQueue> Queues { get; set; } = new Dictionary<string, TasksQueue>();
        public static TasksQueue GetQueue(string name)
        {
            if (Queues.ContainsKey(name))
            {
                return Queues[name];
            }
            else
            {
                var queue = new TasksQueue();
                Queues.Add(name, queue);
                Task.Run(() =>
                {
                    queue.Execute();
                });
                return queue;
            }
        }
    }

    public class TasksQueue
    {
        private Queue<Func<Task>> queue = new Queue<Func<Task>>();
        private ManualResetEventSlim queueEmptyEvent = new ManualResetEventSlim();
        private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

        public void Enqueue(Func<Task> task)
        {
            lock (queue)
            {
                queue.Enqueue(task);
            }
            queueEmptyEvent.Set();
        }

        public void Execute()
        {
            while (!cancellationTokenSource.Token.IsCancellationRequested)
            {
                queueEmptyEvent.Wait(cancellationTokenSource.Token);
                while (true)
                {
                    Func<Task> taskFunc;
                    lock (queue)
                    {
                        if (queue.Count > 0)
                        {
                            taskFunc = queue.Dequeue();
                        }
                        else
                        {
                            break;
                        }
                    }
                    taskFunc().Wait();
                    if (queue.Count == 0)
                    {
                        queueEmptyEvent.Reset();
                    }
                }
            }
        }

        public void Stop()
        {
            cancellationTokenSource.Cancel();
        }
    }


}
